<?php
namespace Admin\Controller;

use Think\Controller;
use Workerman\Worker;

// import('Vendor.workerman-for-win-master.Worker');

class WorkerController extends Controller
{
    // private $worker;
    public function index()
    {
        global $worker;
        /*// if (!IS_CLI) {
        //     die("无法直接访问，请通过命令行启动");
        // }

        $worker = new \Workerman\Worker('websocket://127.0.0.1:2346');
        // dump($worker);
        // 当收到客户端发来的数据后返回hello $data给客户端
        $worker->onWorkerStart = function ($worker) {
        echo "Worker starting...\n";
        };
        $worker->onMessage = function ($connection, $data) {
        // 向客户端发送hello $data
        $connection->send('hello一起 ' . $data);
        };
        // 运行worker
        Worker::runAll();*/

        // 初始化一个worker容器，监听1234端口
        $worker = new Worker('websocket://127.0.0.1:1234');
        // 这里进程数必须设置为1
        $worker->count = 1;
        // worker进程启动后建立一个内部通讯端口
        $worker->onWorkerStart = function ($worker) {
            // 开启一个内部端口，方便内部系统推送数据，Text协议格式 文本+换行符
            $inner_text_worker = new Worker('tcp://127.0.0.1:5678');
            
            $inner_text_worker->onMessage = function ($connection, $buffer) {
                global $worker;
                // $data数组格式，里面有uid，表示向那个uid的页面推送数据
                $data = json_decode($buffer, true);
                $uid = $data['uid'];
                // 通过workerman，向uid的页面推送数据
                $ret = $this->sendMessageByUid($uid, $buffer);
                // 返回推送结果
                $connection->send($ret ? 'ok' : 'fail');
            };
            $inner_text_worker->listen();
        };
        // 新增加一个属性，用来保存uid到connection的映射
        $worker->uidConnections = array();
        // 当有客户端发来消息时执行的回调函数
        $worker->onMessage = function ($connection, $data) use ($worker) {
            // 判断当前客户端是否已经验证,既是否设置了uid
            if (!isset($connection->uid)) {
                // 没验证的话把第一个包当做uid（这里为了方便演示，没做真正的验证）
                $connection->uid = $data;
                /* 保存uid到connection的映射，这样可以方便的通过uid查找connection，
                 * 实现针对特定uid推送数据
                 */
                $worker->uidConnections[$connection->uid] = $connection;
                return;
            }
        };

        // 当有客户端连接断开时
        $worker->onClose = function ($connection) use ($worker) {
            global $worker;
            if (isset($connection->uid)) {
                // 连接断开时删除映射
                unset($worker->uidConnections[$connection->uid]);
            }
        };
        // 运行所有的worker（其实当前只定义了一个）
        Worker::runAll();

    }
    // 向所有验证的用户推送数据
    public function broadcast($message)
    {
        global $worker;
        foreach ($worker->uidConnections as $connection) {
            $connection->send($message);
        }
    }

// 针对uid推送数据
    public function sendMessageByUid($uid, $message)
    {
        global $worker;
        if (isset($worker->uidConnections[$uid])) {
            $connection = $worker->uidConnections[$uid];
            $connection->send($message);
            return true;
        }
        return false;
    }
    public function sendMsg($msg)
    {
        header("Content-Type: text/html; charset=UTF-8");
        // 建立socket连接到内部推送端口
        $client = stream_socket_client('tcp://127.0.0.1:5678', $errno, $errmsg, 1);
        // 推送的数据，包含uid字段，表示是给这个uid推送
        $data = array('uid' => 139, 'percent' => '88%',"msg"=>$msg);
        // 发送数据，注意5678端口是Text协议的端口，Text协议需要在数据末尾加上换行符
        fwrite($client, json_encode($data) . "\n");
        // 读取推送结果
        echo fread($client, 8192);
    }
}
